use crate::{lexer::LineColumnLocation, CompileError, CompileTarget};

#[derive(Clone, Copy, Debug)]
pub enum ErrorLocation {
    Point(LineColumnLocation),
    Range(LineColumnLocation, LineColumnLocation),
}

pub fn generate_error_message<Target: CompileTarget>(
    source: &str,
    error: CompileError<Target>,
) -> String {
    let location = error.location();
    let mut error = vec![format!("Error: {}", error)];
    if let Some(location) = location {
        match location {
            ErrorLocation::Point(start) => {
                error.push(format!("{}", start));
                let line = start.line().get();
                let line_str = line.to_string();
                let line_source = source.lines().nth(line - 1).unwrap_or_default();
                let padding = " ".repeat(line_str.len());

                error.push(format!("{} |", padding));
                error.push(format!("{} | {}", line_str, line_source));
                error.push(format!(
                    "{} | {}^",
                    padding,
                    " ".repeat(start.column().get() - 1)
                ));
            }
            ErrorLocation::Range(start, end) => {
                error.push(format!("{}", start));
                if start.line() == end.line() {
                    let line = start.line().get();
                    let line_str = line.to_string();
                    let line_source = source.lines().nth(line - 1).unwrap_or_default();
                    let padding = " ".repeat(line_str.len());

                    error.push(format!("{} |", padding));
                    error.push(format!("{} | {}", line_str, line_source));
                    error.push(format!(
                        "{} | {}{}",
                        padding,
                        " ".repeat(start.column().get() - 1),
                        "^".repeat(end.column().get() - start.column().get())
                    ));
                } else {
                    todo!()
                }
            }
        }
    }
    error.join("\n")
}
